import fs from 'fs';
import path from 'path';
import express from 'express';
import type { Server as HttpServer } from 'http';
import https from 'https';
import http from 'http';
import { HttpsProxyAgent } from 'https-proxy-agent';
import type { Request, Response, NextFunction } from 'express';

const mobileUserAgentPattern = /mobile|android|iphone|ipad/i;
const douyinDesktopUa =
  'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 Edg/136.0.0.0';

const resolveStaticRoot = () => path.resolve(__dirname, '..', '..', 'web', 'dist');

// 获取上游代理配置
const getUpstreamProxyAgent = () => {
  const proxyUrl = process.env.DOUYIN_PROXY || process.env.UPSTREAM_PROXY;
  if (!proxyUrl) {
    return undefined;
  }

  try {
    // 格式化代理地址
    let formattedUrl = proxyUrl;
    if (!/^https?:\/\//.test(proxyUrl)) {
      formattedUrl = `http://${proxyUrl}`;
    }

    const agent = new HttpsProxyAgent(formattedUrl);
    console.log(`🌐 [proxy-server] 使用上游代理: ${formattedUrl}`);
    return agent;
  } catch (error) {
    console.error('❌ [proxy-server] 创建代理 agent 失败:', error);
    return undefined;
  }
};

// 自定义 HTTPS 代理中间件
const createCustomHttpsProxy = (
  target: string,
  options: {
    pathRewrite?: (path: string) => string;
    agent?: any;
    onProxyReq?: (proxyReq: http.ClientRequest, req: Request) => void;
    onProxyRes?: (proxyRes: http.IncomingMessage, res: Response) => void;
  } = {}
) => {
  return (req: Request, res: Response, next: NextFunction) => {
    try {
      // 路径重写
      let targetPath = req.url;
      if (options.pathRewrite) {
        targetPath = options.pathRewrite(req.url);
      }

      const targetUrl = new URL(targetPath, target);

      // 准备请求头
      const headers = { ...req.headers };

      // 修改 User-Agent（如果是移动端）
      if (mobileUserAgentPattern.test(headers['user-agent'] || '')) {
        headers['user-agent'] = douyinDesktopUa;
      }

      // 设置 Referer
      headers['referer'] = target;

      // 删除 host（会自动设置）
      delete headers['host'];

      // 创建请求选项
      const requestOptions: https.RequestOptions = {
        hostname: targetUrl.hostname,
        port: targetUrl.port || 443,
        path: targetUrl.pathname + targetUrl.search,
        method: req.method,
        headers: headers,
        agent: options.agent, // 使用代理 agent
      };

      // 发起请求
      const proxyReq = https.request(requestOptions, (proxyRes) => {
        // 处理响应头（Cookie 处理）
        if (proxyRes.headers['set-cookie']) {
          proxyRes.headers['set-cookie'] = proxyRes.headers['set-cookie'].map((cookie) =>
            cookie
              .replace(/; Domain=[^;]+/i, '')
              .replace(/; SameSite=None/i, '')
              .replace(/; Secure=true/i, '')
          );
        }

        // 回调
        if (options.onProxyRes) {
          options.onProxyRes(proxyRes, res);
        }

        // 设置响应头
        res.writeHead(proxyRes.statusCode || 200, proxyRes.headers);

        // 转发响应体
        proxyRes.pipe(res);
      });

      // 回调
      if (options.onProxyReq) {
        options.onProxyReq(proxyReq, req);
      }

      // 错误处理
      proxyReq.on('error', (error) => {
        console.error('[proxy] 请求错误:', error);
        if (!res.headersSent) {
          res.status(502).send('Proxy Error');
        }
      });

      // 转发请求体
      req.pipe(proxyReq);
    } catch (error) {
      console.error('[proxy] 代理中间件错误:', error);
      if (!res.headersSent) {
        res.status(500).send('Internal Proxy Error');
      }
    }
  };
};

const createProxyApp = () => {
  const proxyApp = express();
  const upstreamAgent = getUpstreamProxyAgent();

  // 代理用户主页请求到 www.douyin.com
  proxyApp.use(
    '/dyuser',
    createCustomHttpsProxy('https://www.douyin.com', {
      pathRewrite: (path) => path.replace(/^\/dyuser/, ''),
      agent: upstreamAgent,
    })
  );

  // 代理直播页面请求到 live.douyin.com
  proxyApp.use(
    '/dylive',
    createCustomHttpsProxy('https://live.douyin.com', {
      pathRewrite: (path) => path.replace(/^\/dylive/, ''),
      agent: upstreamAgent,
    })
  );

  // WebSocket 代理 - 使用自定义实现
  // 注意：WebSocket 需要在服务器的 upgrade 事件中处理，不在这里配置

  const staticRoot = resolveStaticRoot();
  if (fs.existsSync(staticRoot)) {
    proxyApp.use(express.static(staticRoot));
    proxyApp.use((req, res, next) => {
      if (req.method !== 'GET') {
        next();
        return;
      }

      if (req.path.startsWith('/dylive') || req.path.startsWith('/socket')) {
        next();
        return;
      }

      const indexPath = path.join(staticRoot, 'index.html');
      fs.access(indexPath, fs.constants.R_OK, (err) => {
        if (err) {
          next(err);
          return;
        }
        res.sendFile(indexPath);
      });
    });
  } else {
    console.warn(`[proxy] 静态目录不存在: ${staticRoot}`);
  }

  return proxyApp;
};

export const startProxyServer = (port: number): HttpServer => {
  const proxyApp = createProxyApp();
  const upstreamAgent = getUpstreamProxyAgent();

  const server = proxyApp.listen(port, () => {
    const staticRoot = resolveStaticRoot();
    console.log(`🌐 Proxy server listening on port ${port}`);
    if (fs.existsSync(staticRoot)) {
      console.log(`🗂️ 提供静态资源目录: ${staticRoot}`);
    }
  });

  // WebSocket 升级处理
  server.on('upgrade', (req, socket, head) => {
    if (req.url?.startsWith('/socket')) {
      // 处理 WebSocket 代理
      const targetPath = req.url.replace(/^\/socket/, '');
      const targetUrl = `wss://webcast5-ws-web-lf.douyin.com${targetPath}`;

      // 修改请求头
      const headers = { ...req.headers };
      if (mobileUserAgentPattern.test(headers['user-agent'] || '')) {
        headers['user-agent'] = douyinDesktopUa;
      }

      // 创建到目标服务器的 WebSocket 连接
      const targetOptions: https.RequestOptions = {
        hostname: 'webcast5-ws-web-lf.douyin.com',
        port: 443,
        path: targetPath,
        method: 'GET',
        headers: {
          ...headers,
          host: 'webcast5-ws-web-lf.douyin.com',
        },
        agent: upstreamAgent, // 使用上游代理
      };

      const proxyReq = https.request(targetOptions);

      proxyReq.on('upgrade', (proxyRes, proxySocket, proxyHead) => {
        // 将客户端升级响应发送回去
        socket.write(
          `HTTP/1.1 ${proxyRes.statusCode} ${proxyRes.statusMessage}\r\n` +
            Object.keys(proxyRes.headers)
              .map((key) => `${key}: ${proxyRes.headers[key]}`)
              .join('\r\n') +
            '\r\n\r\n'
        );

        // 双向转发数据
        proxySocket.pipe(socket);
        socket.pipe(proxySocket);

        // 错误处理
        proxySocket.on('error', (err) => {
          console.error('[WS Proxy] 目标 socket 错误:', err);
          socket.destroy();
        });

        socket.on('error', (err) => {
          console.error('[WS Proxy] 客户端 socket 错误:', err);
          proxySocket.destroy();
        });
      });

      proxyReq.on('error', (err) => {
        console.error('[WS Proxy] 升级请求错误:', err);
        socket.destroy();
      });

      // 写入升级请求头
      proxyReq.end();

      // 将原始请求的 head 数据写入代理 socket
      if (head && head.length > 0) {
        socket.once('data', (data) => {
          proxyReq.write(data);
        });
      }
    } else {
      socket.destroy();
    }
  });

  return server;
};
